package com.andriology.logic;

import java.util.TreeMap;

import android.os.Parcel;
import android.os.Parcelable;


public class TestResult implements Parcelable{

	private final int  RANGE_MIN_VAL = 0;
	private final int  RANGE_MAX_VAL = 100;
	/*private final int SCALING_FACTOR = 100;*/
	private int finalResult;
	private int numOfHighlyWeightedAnswers;
	private int numOfMiddleWeightedAnswers;
	private int numOfLowWeightedAnswers;
	
	public int getNumOfLowWeightedAnswers() {
		return numOfLowWeightedAnswers;
	}


	public void incNumOfLowWeightedAnswers() {
		this.numOfLowWeightedAnswers++;
	}

	public void decNumOfLowWeightedAnswers() {
		this.numOfLowWeightedAnswers--;
	}
	
	public int getNumOfHighlyWeightedAnswers() {
		return numOfHighlyWeightedAnswers;
	}


	public void incNumOfHighlyWeightedAnswers() {
		this.numOfHighlyWeightedAnswers++;
	}

	public void decNumOfHighlyWeightedAnswers() {
		this.numOfHighlyWeightedAnswers--;
	}
	
	public int getNumOfMiddleWeightedAnswers() {
		return numOfMiddleWeightedAnswers;
	}


	public void incNumOfMiddleWeightedAnswers() {
		this.numOfMiddleWeightedAnswers++;
	}

	public void decNumOfMiddleWeightedAnswers() {
		this.numOfMiddleWeightedAnswers--;
	}

	/* A Map is an object that maps keys to values. A map cannot contain duplicate keys. Tree Map is a sorted according to its key
	 * This tree map will hold the lower bound of each range and its corresponding message/advice pair.
	 * For example:
	 * (0 ->9 ), Message 1, Advice 1
	 * (10->19), Message 2, Advice 2
	 * this will be saved in my tree map (sorted map according to key values)
	 * then use map.floorKey to get the largest key that is less that or equal to my given input
	 * */
	private TreeMap<Integer, AdviceMessagePair> treeMap;
	
	/* Since we don't have an exact equation of how different combinations of answers leads the final result, I have to map given keys (number of
	 * highly-weighted answers and number of middle-weighted answers) to actual result that appears to user.*/
	private TreeMap<Integer, TreeMap<Integer, Integer>> finalMarkTreeMap;
	
	private static class AdviceMessagePair implements Parcelable{
		private String advice;
		private String message;
		

		public void setAdviceMessagePair(String message, String advice){
			this.advice = advice;
			this.message = message;
		}
		
		public String getMessage(){
			return this.message;
		}
		
		public String getAdvice(){
			return this.advice;
		}

		@Override
		public int describeContents() {
			return 0;
		}

		@Override
		public void writeToParcel(Parcel out, int flags) {
			out.writeString(advice);
			out.writeString(message);
		}
		
		@SuppressWarnings("unused")
		public static final Parcelable.Creator<AdviceMessagePair> CREATOR = new Parcelable.Creator<AdviceMessagePair>() {
			
			@Override
			public AdviceMessagePair[] newArray(int size) {
				return new AdviceMessagePair[size];
			}
			
			@Override
			public AdviceMessagePair createFromParcel(Parcel source) {
				return new AdviceMessagePair(source);
			}
		};
		
		public AdviceMessagePair(Parcel in) {
			advice = in.readString();
			message = in.readString();
		}

		public AdviceMessagePair() {
		}
	}

	public TestResult(){
		treeMap = new TreeMap<Integer, AdviceMessagePair>();
		finalMarkTreeMap = new TreeMap<Integer, TreeMap<Integer,Integer>>();
		finalResult = 0;
		numOfHighlyWeightedAnswers = 0;
		numOfMiddleWeightedAnswers = 0;
		numOfLowWeightedAnswers    = 0;
	}
	

	public void setRangesMessages (int [] ranges, String [] messages, String[] advices){
		if ((ranges.length != messages.length)|| 
				(ranges.length != advices.length)) 
			return;
		
		for(int i=0; i<ranges.length; i++){
			AdviceMessagePair pair = new AdviceMessagePair();
			pair.setAdviceMessagePair(messages[i], advices[i]);
			treeMap.put(ranges[i], pair);
		}
	}
	
	public String getRangeMessage(int value){
		if ((value <RANGE_MIN_VAL) || (value > RANGE_MAX_VAL))
			return null;
		else
			return treeMap.floorEntry(value).getValue().getMessage();
	}
	
	public String getRangeAdvice(int value){
		if ((value <RANGE_MIN_VAL) || (value>RANGE_MAX_VAL))
			return null;
		else
			return treeMap.floorEntry(value).getValue().getAdvice();
	}
	
	public int getFinalResult() {
		return finalResult;
	}
	
	public void setFinalResult(int result) {
		 finalResult = result;
	}
	
	/*public void addValue (int amount){
		this.finalResult += amount;
	}*/
	
	/*public void subtractValue (int amount){
		this.finalResult -= amount;
	}*/
	
	/*public double calcPercentage(int numOfQuestions){
		
		return (finalResult*SCALING_FACTOR)/(numOfQuestions*TestQuestion.FINAL_MARK);
	}*/

	@Override
	public int describeContents() {
		return 0;
	}

	@Override
	public void writeToParcel(Parcel out, int flags) {
		out.writeInt(finalResult);
		out.writeInt(numOfHighlyWeightedAnswers);
		out.writeInt(numOfMiddleWeightedAnswers);
		out.writeInt(numOfLowWeightedAnswers);
		
		out.writeMap(treeMap);
		out.writeMap(finalMarkTreeMap);
	}
	
	public final static Parcelable.Creator<TestResult> CREATOR = new Creator<TestResult>() {
		
		@Override
		public TestResult[] newArray(int size) {
			return new TestResult[size];
		}
		
		@Override
		public TestResult createFromParcel(Parcel source) {
			return new TestResult(source);
		}
	};
	
	public TestResult(Parcel in) {
		finalResult = in.readInt();
		numOfHighlyWeightedAnswers = in.readInt();
		numOfMiddleWeightedAnswers = in.readInt();
		numOfLowWeightedAnswers    = in.readInt();
		
		treeMap = new TreeMap<Integer, AdviceMessagePair>();
		finalMarkTreeMap = new TreeMap<Integer, TreeMap<Integer,Integer>>();
		
		in.readMap(treeMap, AdviceMessagePair.class.getClassLoader());
		in.readMap(finalMarkTreeMap, null);
	}
	
	/* This method construct the path on how to reach actual result as a function of the number of highly-answered questions, number of middle-weighted questions*/
	public void setFinalResultPathMap(int [] ActualResults, int numberOfQuestions) {
		
		int index = 0;
		
		for (int HW_AnswersNum = 0; HW_AnswersNum <=numberOfQuestions ; HW_AnswersNum++){
			
			TreeMap<Integer, Integer> nestedTreeMap = new TreeMap<Integer, Integer>();
			for(int MW_AnswersNum = 0; MW_AnswersNum <= (numberOfQuestions - HW_AnswersNum); MW_AnswersNum++,index++ )
			{
				nestedTreeMap.put(MW_AnswersNum, ActualResults[index]);
			}
			
			finalMarkTreeMap.put(HW_AnswersNum, nestedTreeMap);
		}
	}

	public int getMappedFinalResultPercent(int x, int y){
		return finalMarkTreeMap.get(x).get(y);
	}
} 